package com.ssy.lingxi.contract.serviceimpl;

import cn.hutool.core.util.NumberUtil;
import com.ssy.lingxi.common.exception.BusinessException;
import com.ssy.lingxi.common.model.dto.UserLoginCacheDTO;
import com.ssy.lingxi.common.response.PageData;
import com.ssy.lingxi.common.response.ResponseCode;
import com.ssy.lingxi.common.response.Wrapper;
import com.ssy.lingxi.contract.api.model.constant.ContractOrderTypeEnum;
import com.ssy.lingxi.contract.api.model.vo.request.ContractExecuteInfoAddVO;
import com.ssy.lingxi.contract.entity.ContractDO;
import com.ssy.lingxi.contract.entity.ContractExecuteInfoDO;
import com.ssy.lingxi.contract.model.vo.applyamount.request.UpdateApplyAmountVO;
import com.ssy.lingxi.contract.model.vo.execute.request.ContractExecuteInfoPageVO;
import com.ssy.lingxi.contract.model.vo.execute.response.ContractExecuteInfoQueryVO;
import com.ssy.lingxi.contract.repository.ContractExecuteInfoRepository;
import com.ssy.lingxi.contract.repository.ContractRepository;
import com.ssy.lingxi.contract.service.IContractExecuteInfoService;
import com.ssy.lingxi.contract.service.IFeignService;
import com.ssy.lingxi.dto.request.ApplyAmountDetailSunQueryVO;
import com.ssy.lingxi.dto.response.ApplyAmountDetailSunVO;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicLong;
import java.util.stream.Collectors;

/**
 * 合同执行情况接口实现
 * @author 伍将
 * @date 2021/3/9
 * @version 2.0.0
 */
@Service
public class ContractExecuteInfoServiceImpl implements IContractExecuteInfoService {

    @Resource
    private ContractExecuteInfoRepository repository;

    @Resource
    private IFeignService feignService;
    @Resource
    private ContractRepository contractRepository;
    /**
     * 批量新增合同执行情况
     * @author 伍将
     * @date 2021/3/9
     * @param addVOList: 新增请求参数
     * @return 操作结果
     **/
    @Override
    public Wrapper<Void> addList(List<ContractExecuteInfoAddVO> addVOList) {

        if (null != addVOList && addVOList.size() > 0) {

            // 验证新增数据是否已存在
            for (ContractExecuteInfoAddVO addVO : addVOList) {
                ContractExecuteInfoDO existEntity = repository.findData(addVO.getContractId(), addVO.getOrderId(), addVO.getOrderType(), addVO.getIsHasTax(), addVO.getTaxRate());
                if (null != existEntity) {
                    throw new BusinessException(ResponseCode.CONTRACT_PURCHASE_INVITE_BID_IS_EXIST);
                }
            }

            // 组装新增对象
            List<ContractExecuteInfoDO> addList = addVOList.stream().map(o -> {
                ContractExecuteInfoDO entity = new ContractExecuteInfoDO();
                entity.setContractId(o.getContractId());
                entity.setOrderId(o.getOrderId());
                entity.setOrderNO(o.getOrderNO());
                entity.setOrderAbstract(o.getOrderAbstract());
                entity.setOrderType(o.getOrderType());
                entity.setOrderTime(o.getOrderTime());
                Double orderAmount=o.getOrderAmount();
                if(ContractOrderTypeEnum.RETURN_GOODS.getCode().equals(o.getOrderType())){
                    orderAmount=-orderAmount;
                }
                entity.setOrderAmount(orderAmount);
                entity.setIsHasTax(o.getIsHasTax());
                entity.setTaxRate(o.getTaxRate());
                entity.setPayAmount(0D);
                entity.setUnPayApplyAmount(0D);
                entity.setCreateTime(System.currentTimeMillis());
                entity.setUpdateTime(System.currentTimeMillis());
                return entity;
            }).collect(Collectors.toList());

            // 保存合同执行情况
            repository.saveAll(addList);
        }

        return Wrapper.success();
    }

    /**
     * 分页查询合同执行情况
     * @author 伍将
     * @date 2021/3/9
     * @param pageVO: 分页请求参数
     * @return 操作结果
     **/
    @Override
    public Wrapper<PageData<ContractExecuteInfoQueryVO>> pageList(UserLoginCacheDTO user,ContractExecuteInfoPageVO pageVO) {

        // step1:校验合同归属甲方或乙方
        ContractDO byId = contractRepository.findById(pageVO.getContractId()).orElse(null);
        if(byId==null
                || (!(byId.getPartyAMemberId().equals(user.getMemberId()) && byId.getPartyARoleId().equals(user.getMemberRoleId()))
                && !(byId.getPartyBMemberId().equals(user.getMemberId()) && byId.getPartyBRoleId().equals(user.getMemberRoleId())))){
            return Wrapper.success(new PageData<>(0L, null));
        }
        // step2: 组装远端调用查询结算合同请款请款请求
        boolean partyAFlag = byId.getPartyAMemberId().equals(user.getMemberId()) && byId.getPartyARoleId().equals(user.getMemberRoleId());
        ApplyAmountDetailSunQueryVO queryVO = new ApplyAmountDetailSunQueryVO();
        queryVO.setContractId(pageVO.getContractId());
        queryVO.setOrderNo(pageVO.getOrderNo());
        queryVO.setOrderAbstract(pageVO.getOrderAbstract());
        queryVO.setStartTime(pageVO.getStartTime());
        queryVO.setEndTime(pageVO.getEndTime());
        queryVO.setCurrent(pageVO.getCurrent());
        queryVO.setPageSize(pageVO.getPageSize());
        queryVO.setPartyAFlag(partyAFlag);
        // step3: 远端调用查询结算合同请款请款
        Wrapper<PageData<ApplyAmountDetailSunVO>> wrapper = feignService.pageContractExecuteDetail(queryVO);
        // step4: 组装数据
        PageData<ApplyAmountDetailSunVO> pageData = wrapper.getData();
        if (pageData.getTotalCount().compareTo(0L) <=0)  {
            return Wrapper.success(new PageData<>(0L, new ArrayList<>()));
        }
        AtomicLong helpId = new AtomicLong(0L);
        List<ContractExecuteInfoQueryVO> list = pageData.getData().stream().map(map -> {
            ContractExecuteInfoQueryVO item = new ContractExecuteInfoQueryVO();
            item.setId(helpId.getAndIncrement());
            item.setOrderId(map.getOrderId());
            item.setOrderNO(map.getOrderNO());
            item.setOrderAbstract(map.getOrderAbstract());
            item.setOrderType(map.getOrderType());
            item.setOrderTypeName(map.getOrderTypeName());
            item.setOrderTime(map.getOrderTime());
            item.setOrderAmount(map.getOrderAmount().doubleValue());
            item.setOrderStatusName(map.getOrderStatusName());
            item.setIsHasTax(map.getHasTax());
            item.setTaxRate(map.getTaxRate().doubleValue());
            item.setPayAmount(map.getPayAmount().doubleValue());
            item.setUnPayApplyAmount(map.getUnPayApplyAmount().doubleValue());
            item.setUnApplyAmount(map.getUnApplyAmount().doubleValue());
            return item;
        }).collect(Collectors.toList());
        return Wrapper.success(new PageData<>(pageData.getTotalCount(), list));
    }

    /**
     * 根据合同执行请款id查询执行请款列表
     * @author 伍将
     * @date 2021/3/10
     * @param idList: 执行请款id
     * @return 操作结果
     **/
    @Override
    public List<ContractExecuteInfoDO> getListById(List<Long> idList) {
        return repository.findAllByIdIn(idList);
    }

    /**
     * 更新合同执行请款金额
     * @author 伍将
     * @date 2021/3/10
     * @param updateVOList: 更新请求参数
     * @return 操作结果
     **/
    @Override
    public Wrapper<Void> updateApplyAmount(List<UpdateApplyAmountVO> updateVOList) {

        if (updateVOList.size() > 0) {
            List<Long> idList = updateVOList.stream().map(UpdateApplyAmountVO::getExecuteId).collect(Collectors.toList());
            List<ContractExecuteInfoDO> updateList = repository.findAllByIdIn(idList);
            if (null == updateList || updateList.size() <= 0) {
                throw new BusinessException(ResponseCode.CONTRACT_EXECUTE_INFO_NOT_EXIST);
            }
            for (ContractExecuteInfoDO item : updateList) {
                UpdateApplyAmountVO updateVO = updateVOList.stream().filter(o -> o.getExecuteId().equals(item.getId())).findFirst().orElse(null);
                if (null == updateVO) {
                    throw new BusinessException(ResponseCode.CONTRACT_EXECUTE_INFO_NOT_EXIST);
                }
                item.setUnPayApplyAmount(NumberUtil.add(item.getUnPayApplyAmount(), updateVO.getApplyAmount()));
            }

            repository.saveAll(updateList);
        }

        return Wrapper.success();
    }
}
